package org.road0329.tools.proto_parse_tool.ems.qgdw3761.utils;

import org.road0329.tools.proto_parse_tool.chargingpile.MsgDcsResult;
import org.road0329.tools.proto_parse_tool.ems.dataobject.gw.GwItemData;
import org.road0329.tools.proto_parse_tool.ems.dataobject.gw.afn04.*;
import org.road0329.tools.proto_parse_tool.utils.NumberUtil;
import org.road0329.tools.proto_parse_tool.utils.ProtocolGW_09Util;
import org.road0329.tools.proto_parse_tool.utils.ProtocolUtils;
import org.road0329.tools.proto_parse_tool.utils.StringUtil;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Created by Administrator on 2018-09-13.
 */
@Component
public class Gw09CallParamUtil {

    public static MsgDcsResult parseCallParamData(byte[] msg, int from, boolean acd) {
        int index = from;
        int fixlen = (msg[index] & 0x80) == 0 ? 2 : 8;
        if (acd) {
            fixlen += 2;
        }
        index++;
        MsgDcsResult gwResult = new MsgDcsResult();
        int n = 0;
        List<GwItemData> gwItemList = new ArrayList<GwItemData>();
        Map<Integer, RtuParamF65F66> paramF6566Map = new HashMap<Integer, RtuParamF65F66>();
        while ((index + fixlen) < msg.length) {
            Integer pn = ProtocolGW_09Util.getPnFromDA(msg[index + 1], msg[index]);
            int fn = ProtocolGW_09Util.getFnFromDT(msg[index + 3], msg[index + 2]);
            index += 4;
            GwItemData item = new GwItemData();
            item.setFn(fn);
            item.setPn(pn);
            switch (fn) {//终端上行通信口通信参数设置
                case 1:
                    RtuParamF1 paramF1 = parseF1Frame(msg, index);
                    item.setData(paramF1);
                    gwItemList.add(item);
                    index += 6;
                    break;
                case 3:
                    RtuParamF3 paramF3 = parseF3Frame(msg, index);
                    item.setData(paramF3);
                    gwItemList.add(item);
                    index += 28;
                    break;
                case 7:
                    RtuParamF7 paramF7 = parseF7Frame(msg, index);
                    item.setData(paramF7);
                    gwItemList.add(item);
                    int m = ProtocolUtils.Unsignd(msg[index + 20]);
                    n = ProtocolUtils.Unsignd(msg[index + 21 + m]);
                    index += 24 + m + n;
                    break;
                case 9:
                    RtuParamF9 paramF9 = parseF9Frame(msg, index);
                    item.setData(paramF9);
                    gwItemList.add(item);
                    index += 16;
                    break;
                case 10:
                    List<RtuParamF10> paramF10List = parseF10Frame(msg, index);
                    item.setData(paramF10List);
                    gwItemList.add(item);
                    int num = ProtocolUtils.Unsignd(msg[index]) + ProtocolUtils.Unsignd(msg[index + 1]) * 0x100;
                    index += 2 + num * 27;
                    break;
                case 12:
                    RtuParamF12 paramF12 = parseF12Frame(msg, index);
                    item.setData(paramF12);
                    gwItemList.add(item);
                    index += 2;
                    break;
                case 26:
                    RtuParamF26 paramF26 = parseF26Frame(msg, index);
                    item.setData(paramF26);
                    gwItemList.add(item);
                    index += 57;
                    break;
                case 57:
                    RtuParamF57 paramF57 = parseF57Frame(msg, index);
                    item.setData(paramF57);
                    gwItemList.add(item);
                    index += 3;
                    break;
                case 65:
                    RtuParamF65F66 paramF65 = parseF6566Frame(msg, index, paramF6566Map, item.getPn());
                    paramF65.setTaskid((short) item.getPn());
                    paramF65.setTasktype((short) 1);
                    item.setData(paramF65);
                    gwItemList.add(item);
                    n = ProtocolUtils.Unsignd(msg[index + 8]);
                    index += 8 + 1 + n * 4;
                    break;
                case 66:
                    RtuParamF65F66 paramF66 = parseF6566Frame(msg, index, paramF6566Map, item.getPn());
                    paramF66.setTaskid((short) item.getPn());
                    paramF66.setTasktype((short) 2);
                    item.setData(paramF66);
                    gwItemList.add(item);
                    n = ProtocolUtils.Unsignd(msg[index + 8]);
                    index += 8 + 1 + n * 4;
                    break;
                case 67:
                    String iseffectF67 = String.format("%02X", msg[index]);
                    if (paramF6566Map.get(item.getPn()) != null) {
                        if ("55".equals(iseffectF67)) {
                            paramF6566Map.get(item.getPn()).setIseffect((short) 1);
                        } else {
                            paramF6566Map.get(item.getPn()).setIseffect((short) 0);
                        }
                    } else {
                        RtuParamF67F68 paramF67 = new RtuParamF67F68();
                        paramF67.setTaskid((short) item.getPn());
                        paramF67.setIseffect((short) (iseffectF67.equals("55") ? 1 : 0));
                        item.setData(paramF67);
                        gwItemList.add(item);
                    }
                    index += 1;
                    break;
                case 68:
                    String iseffectF68 = String.format("%02X", msg[index]);
                    if (paramF6566Map.get(item.getPn()) != null) {
                        if ("55".equals(iseffectF68)) {
                            paramF6566Map.get(item.getPn()).setIseffect((short) 1);
                        } else {
                            paramF6566Map.get(item.getPn()).setIseffect((short) 0);
                        }
                    } else {
                        RtuParamF67F68 paramF68 = new RtuParamF67F68();
                        paramF68.setTaskid((short) item.getPn());
                        paramF68.setIseffect((short) (iseffectF68.equals("55") ? 1 : 0));
                        item.setData(paramF68);
                        gwItemList.add(item);
                    }
                    index += 1;
                    break;
            }
        }
        gwResult.setData(gwItemList);
        gwResult.setSuccess(true);
        gwResult.setMessage("成功");
        return gwResult;
    }

    private static RtuParamF12 parseF12Frame(byte[] byteValue, int index) {
        RtuParamF12 param12 = new RtuParamF12();
        List<Integer> joinRounds = new ArrayList<Integer>();
        List<Integer> openRounds = new ArrayList<Integer>();
        ;
        String joinRoundstring = StringUtil.revert(StringUtil.AddjustLength(Integer.toBinaryString(ProtocolUtils.Unsignd(byteValue[index++])), 8, "0"));
        for (int i = 0; i < 8; i++) {
            if ("1".equals(joinRoundstring.substring(i, i + 1))) {
                joinRounds.add(i + 1);
            }
        }
        String openRoundstring = StringUtil.revert(StringUtil.AddjustLength(Integer.toBinaryString(ProtocolUtils.Unsignd(byteValue[index++])), 8, "0"));
        for (int i = 0; i < 8; i++) {
            if ("1".equals(openRoundstring.substring(i, i + 1))) {
                openRounds.add(i + 1);
            }
        }
        param12.setJoinRounds(joinRounds);
        param12.setOpenRounds(openRounds);
        return param12;
    }

    private static RtuParamF26 parseF26Frame(byte[] byteValue, int index) {
        RtuParamF26 param26 = new RtuParamF26();
        param26.setVup(ProtocolGW_09Util.parseA7(byteValue, index));
        index += 2;
        param26.setVdown(ProtocolGW_09Util.parseA7(byteValue, index));
        index += 2;
        param26.setVoff(ProtocolGW_09Util.parseA7(byteValue, index));
        index += 2;
        //电压上上限（过压门限）
        param26.setVupup(ProtocolGW_09Util.parseA7(byteValue, index));
        index += 2;
        param26.setVupuptime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setVupupfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //电压下下限（欠压门限
        param26.setVdowndown(ProtocolGW_09Util.parseA7(byteValue, index));
        index += 2;
        param26.setVdowndowntime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setVdowndownfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //相电流上上限（过流门限）
        param26.setIupup(ProtocolGW_09Util.parseA25(byteValue, index));
        index += 3;
        param26.setIupuptime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setIupupfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //相电流上限（额定电流门限）
        param26.setIup(ProtocolGW_09Util.parseA25(byteValue, index));
        index += 3;
        param26.setIuptime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setIupfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //零序电流上限
        param26.setI0up(ProtocolGW_09Util.parseA25(byteValue, index));
        index += 3;
        param26.setI0uptime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setI0upfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //视在功率上上限
        param26.setPupup(ProtocolGW_09Util.parseA23(byteValue, index));
        index += 3;
        param26.setPupuptime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setPupupfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //视在功率上限
        param26.setPup(ProtocolGW_09Util.parseA23(byteValue, index));
        index += 3;
        param26.setPuptime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setPupfactor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //三相电压不平衡限值
        param26.setV3rate(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        param26.setV3time((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setV3factor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        //三相电流不平衡限值
        param26.setI3rate(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        param26.setI3time((short) ProtocolUtils.Unsignd(byteValue[index++]));
        param26.setI3factor(ProtocolGW_09Util.parseA5(byteValue, index));
        index += 2;
        param26.setVlosttime((short) ProtocolUtils.Unsignd(byteValue[index++]));
        return param26;
    }

    private static RtuParamF57 parseF57Frame(byte[] byteValue, int index) {
        RtuParamF57 param57 = new RtuParamF57();
        List<Integer> allowAlarmList = new ArrayList<Integer>();
        for (int i = 0; i < 3; i++) {
            String allowstring = StringUtil.revert(StringUtil.AddjustLength(Integer.toBinaryString(ProtocolUtils.Unsignd(byteValue[index++])), 8, "0"));
            for (int j = 0; j < 8; j++) {
                if ("1".equals(allowstring.substring(j, j + 1))) {
                    allowAlarmList.add((i * 8) + j);
                }
            }
        }
        param57.setAllowAlarmList(allowAlarmList);
        return param57;
    }

    private static List<RtuParamF10> parseF10Frame(byte[] byteValue, int index) {
        List<RtuParamF10> paramF10List = new ArrayList<RtuParamF10>();
        int num = ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]);//本次电能表/交流采样装置配置数量n
        index = index + 2;
        String commAddr = null;
        for (int i = 0; i < num; i++) {
            RtuParamF10 paramF10 = new RtuParamF10();
            paramF10.setDevId(ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]));
            index = index + 2;
            paramF10.setPn(ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]));
            index = index + 2;
            paramF10.setRate(ProtocolUtils.Unsignd((byte) ((byteValue[index]) >> 5)) & 0x07);
            paramF10.setPort(ProtocolUtils.Unsignd((byte) (byteValue[index] & 0x1F)));
            index++;
            paramF10.setProtocol(ProtocolUtils.Unsignd(byteValue[index++]));
            commAddr = StringUtil.AddjustLength(String.valueOf(ProtocolGW_09Util.parseA12(byteValue, index)), 12, "0");
            if (paramF10.getProtocol() == 32) {
                paramF10.setCommAddr(String.format("%02X", ProtocolUtils.Unsignd(byteValue[index + 6 + 6 + 1])) + commAddr );
            } else {
                paramF10.setCommAddr(commAddr);
            }
            index = index + 6;
            String compwd = "";
            for (int k = 0; k < 6; k++) {
                compwd = NumberUtil.num2PadString((int) byteValue[index++], 16, 2, "0") + compwd;
            }
            paramF10.setCommPwd(compwd);
            paramF10.setTarrifNum((short) ProtocolUtils.Unsignd((byte) (byteValue[index++] & 0x1F)));
            paramF10.setIntegerNum((short) ProtocolUtils.Unsignd((byte) ((byte) (byteValue[index] & 0x0C) >> 2)));
            paramF10.setDecimalNum((short) ProtocolUtils.Unsignd((byte) (byteValue[index] & 0x03)));
            index++;
            paramF10.setRepeaterCommAddr(StringUtil.AddjustLength(String.valueOf(ProtocolGW_09Util.parseA12(byteValue, index)), 12, "0"));
            index = index + 6;
            paramF10.setType(String.format("%02X", byteValue[index++]));

            paramF10List.add(paramF10);
        }
        return paramF10List;
    }

    private static RtuParamF7 parseF7Frame(byte[] byteValue, int index) {
        RtuParamF7 paramF7 = new RtuParamF7();
        paramF7.setIp(String.valueOf(ProtocolUtils.Unsignd(byteValue[index])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 1])) + "."
                + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 2])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 3])));
        index = index + 4;
        paramF7.setMask(String.valueOf(ProtocolUtils.Unsignd(byteValue[index])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 1])) + "."
                + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 2])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 3])));
        index = index + 4;
        paramF7.setGateway(String.valueOf(ProtocolUtils.Unsignd(byteValue[index])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 1])) + "."
                + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 2])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 3])));
        index = index + 4;
        paramF7.setProxyType((short) ProtocolUtils.Unsignd(byteValue[index++]));
        paramF7.setProxyServerIp(String.valueOf(ProtocolUtils.Unsignd(byteValue[index])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 1])) + "."
                + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 2])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 3])));
        index = index + 4;
        paramF7.setProxyServerPort(ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]));
        index = index + 2;
        paramF7.setProxyServerConnType((short) ProtocolUtils.Unsignd(byteValue[index++]));
        int namelength = ProtocolUtils.Unsignd(byteValue[index++]);
        StringBuffer name = new StringBuffer();
        for (int i = 0; i < namelength; i++) {
            name.append((char) byteValue[index + i]);
        }
        paramF7.setProxyServerUsername(name.toString());
        index = index + namelength;
        int pwdlength = ProtocolUtils.Unsignd(byteValue[index++]);
        StringBuffer pwd = new StringBuffer();
        for (int i = 0; i < pwdlength; i++) {
            pwd.append((char) byteValue[index]);
        }
        paramF7.setProxyServerPwd(pwd.toString());
        index = index + pwdlength;
        paramF7.setListeningPort(ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]));
        return paramF7;
    }

    private static RtuParamF9 parseF9Frame(byte[] byteValue, int index) {
        RtuParamF9 param9 = new RtuParamF9();
        List<Integer> effectErcList = new ArrayList<Integer>();
        for (int i = 0; i < 8; i++) {
            String effectstring = StringUtil.revert(StringUtil.AddjustLength(Integer.toBinaryString(ProtocolUtils.Unsignd(byteValue[index++])), 8, "0"));
            for (int j = 0; j < 8; j++) {
                if ("1".equals(effectstring.substring(j, j + 1))) {
                    effectErcList.add((i * 8) + (j + 1));
                }
            }
        }
        List<Integer> importantErcList = new ArrayList<Integer>();
        for (int i = 0; i < 8; i++) {
            String important = StringUtil.revert(StringUtil.AddjustLength(Integer.toBinaryString(ProtocolUtils.Unsignd(byteValue[index++])), 8, "0"));
            for (int j = 0; j < 8; j++) {
                if ("1".equals(important.substring(j, j + 1))) {
                    importantErcList.add((i * 8) + (j + 1));
                }
            }
        }
        param9.setEffectErcList(effectErcList);
        param9.setImportantErcList(importantErcList);
        return param9;
    }

    private static RtuParamF3 parseF3Frame(byte[] byteValue, int index) {
        RtuParamF3 paramF3 = new RtuParamF3();
        paramF3.setIp(String.valueOf(ProtocolUtils.Unsignd(byteValue[index])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 1])) + "."
                + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 2])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 3])));
        index = index + 4;
        paramF3.setPort(ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]));
        index = index + 2;
        paramF3.setIp2(String.valueOf(ProtocolUtils.Unsignd(byteValue[index])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 1])) + "."
                + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 2])) + "." + String.valueOf(ProtocolUtils.Unsignd(byteValue[index + 3])));
        index = index + 4;
        paramF3.setPort2(ProtocolUtils.byteToShort(byteValue[index + 1], byteValue[index]));
        index = index + 2;
        StringBuffer apn = new StringBuffer();
        for (int i = 0; i < 16; i++) {
            if (byteValue[index + i] != 0) {
                apn.append((char) byteValue[index + i]);
            }
        }
        paramF3.setApn(apn.toString());
        return paramF3;
    }

    private static RtuParamF65F66 parseF6566Frame(byte[] byteValue, int index, Map<Integer, RtuParamF65F66> paramF6566Map, int pn) {
        RtuParamF65F66 paramF6566 = new RtuParamF65F66();
        paramF6566.setCycletype((short) ProtocolUtils.Unsignd((byte) ((byteValue[index] & 0xff) >> 6)));
        paramF6566.setPeriod(ProtocolUtils.Unsignd((byte) (byteValue[index] & 0x3F)));
        index++;
        paramF6566.setDt(ProtocolGW_09Util.parseA1(byteValue, index));
        index = index + 6;
        paramF6566.setR((short) ProtocolUtils.Unsignd((byte) byteValue[index++]));
        int num = ProtocolUtils.Unsignd((byte) byteValue[index++]);
        List<Integer> fnList = new ArrayList<Integer>();
        List<Integer> pnList = new ArrayList<Integer>();
        Set<Integer> fnset = new HashSet<Integer>();
        Set<Integer> pnset = new HashSet<Integer>();
        for (int i = 0; i < num; i++) {
            Integer pnnumber = ProtocolGW_09Util.getPnFromDA(byteValue[index + 1], byteValue[index]);
            index = index + 2;
            Integer fnnumber = ProtocolGW_09Util.getFnFromDT(byteValue[index + 1], byteValue[index]);
            index = index + 2;
            fnset.add(fnnumber);
            pnset.add(pnnumber);
        }
        fnList.addAll(fnset);
        pnList.addAll(pnset);
        paramF6566.setFnList(fnList);
        paramF6566.setPnList(pnList);
        paramF6566Map.put(pn, paramF6566);
        return paramF6566;
    }

    private static RtuParamF1 parseF1Frame(byte[] byteValue, int index) {
        RtuParamF1 paramF1 = new RtuParamF1();
        paramF1.setRts((short) ProtocolUtils.Unsignd(byteValue[index++]));
        paramF1.setStartDelayTimes((short) ProtocolUtils.Unsignd(byteValue[index++]));
        String timeout = StringUtil.AddjustLength(Integer.toBinaryString(byteValue[index + 1]), 8, "0").substring(5);//取后三位
        timeout = timeout + StringUtil.AddjustLength(Integer.toBinaryString(byteValue[index]), 8, "0");//第二个字节D0~D3+第一个字节的D0~D7
        paramF1.setResponseTimes(Integer.valueOf(timeout, 2).shortValue());
        paramF1.setSendCount((short) ProtocolUtils.Unsignd((byte) ((byteValue[index + 1] >> 4) & 0x03)));
        index = index + 2;
        paramF1.setCon((short) ProtocolUtils.Unsignd((byte) (byteValue[index++] & 0x07)));
        paramF1.setHeartbeatCycle(byteValue[index++]);
        return paramF1;
    }

}
